
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#include <ngx_config.h>
#include <ngx_core.h>


ngx_int_t
ngx_daemon(ngx_log_t *log)
{
    int  fd;
    ngx_log_error(NGX_LOG_NOTICE, log, 0, "===开始创建子进程===");
	//创建子进程
	pid_t pid;
	pid = fork();
    switch (pid) {
    case -1:
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
        return NGX_ERROR;

    case 0:
        break;

    default:
        exit(0);
    }
	
	//2024.7.3: 由于子进程创建成功，后面的代码父子进程都会执行，所以打印日志会出现两次。
    ngx_parent = ngx_pid;
    ngx_pid = ngx_getpid();
	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===子进程创建完毕。这里会执行两次。子进程pid=%l, 父进程pid=%l===", pid, getppid());

	//2024.7.3: setsid()调用成功后，返回新的会话的ID，调用setsid函数的进程成为新的会话的领头进程，
	//并与其父进程的会话组和进程组脱离。由于会话对控制终端的独占性，进程同时与控制终端脱离。
    if (setsid() == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
        return NGX_ERROR;
    }
	//为子进程设置用户掩码
    umask(0);
	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===设置用户掩码===");

	//打开一个新的文件
    fd = open("/dev/null", O_RDWR);
	
	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===子进程打开/dev/null===");
    if (fd == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "open(\"/dev/null\") failed");
        return NGX_ERROR;
    }
	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===ngx_daemon0005===");

    if (dup2(fd, STDIN_FILENO) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
        return NGX_ERROR;
    }
	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===ngx_daemon0006===");

    if (dup2(fd, STDOUT_FILENO) == -1) {		
		ngx_write_stdout("===ngx_daemon0006.1===\r\n");	
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
        return NGX_ERROR;
    }
	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===ngx_daemon0007===");	

#if 0
    if (dup2(fd, STDERR_FILENO) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
        return NGX_ERROR;
    }
#endif

	ngx_log_error(NGX_LOG_NOTICE, log, 0, "===ngx_daemon0008===");

    if (fd > STDERR_FILENO) {
        if (close(fd) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}
